﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataAccess;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Configuration;

namespace SPIWareMVVM.ViewModels
{
    public static class ApplicationData
    {
        public static bool ShowAllWOParts = false;

        public static ObservableCollection<MachineProduction> RunTimeList
        {
            get
            {
                //1/1/1753 
                if (SelectedRunDate > new DateTime(1753,1,1))
                {
                    ObservableCollection<MachineProduction> dayRun = DataContext.MachineProductions
                                        .Where(d => d.EndTime <= SelectedRunDate.AddDays(1) && d.StartTime >= SelectedRunDate)
                                        .ToObservableCollection<MachineProduction>();
                    return dayRun;
                }
                return new ObservableCollection<MachineProduction>();
            }
        }
        static DateTime _selectedRunDate { get; set; }
        public static DateTime SelectedRunDate
        {
            get { return _selectedRunDate; }
            set
            {
                _selectedRunDate = value;
                //ObservableCollection<MachineProduction> dayRun = DataContext.MachineProductions
                //    .Where(d => d.EndTime <= SelectedRunDate.AddDays(1) && d.StartTime >= SelectedRunDate)
                //    .ToObservableCollection<MachineProduction>();
                //RunTimeList = dayRun;
            }
        }
        public static ObservableCollection<MachineRunTime> SetMachineRunTimes()
        {
            ObservableCollection<MachineRunTime> list = new ObservableCollection<MachineRunTime>();
            foreach (MachineProduction mProd in RunTimeList)
            {
                //filter out non-selected listbox rundates ???
                bool found = false;
                foreach (MachineRunTime mrt in list)
                {
                    if (mrt.MachineNumber == (mProd.MachinePress != null ? mProd.MachinePress.MachineNumber : string.Empty))
                    {
                        mrt.RunTime += (DateTime)mProd.EndTime - (DateTime)mProd.StartTime;
                        found = true;
                        break;
                    }
                }
                if (!found) list.Add(new MachineRunTime(mProd));
            }
            return list;
        }
        public static ObservableCollection<OperatorRunTime> SetOperatorRunTimes()
        {
            ObservableCollection<OperatorRunTime> list = new ObservableCollection<OperatorRunTime>();
            foreach (MachineProduction mProd in RunTimeList)
            {
                bool found = false;
                foreach (OperatorRunTime ort in list)
                {
                    if (ort.OperatorName == (mProd.ApplicationUser != null ? mProd.ApplicationUser.FirstName : string.Empty))
                    {
                        ort.RunTime += (DateTime)mProd.EndTime - (DateTime)mProd.StartTime;
                        found = true;
                        break;
                    }
                }
                if (!found) list.Add(new OperatorRunTime(mProd));
            }
            return list;
        }
        public static TimeSpan SetTotalRunTime()
        {
            TimeSpan results = new TimeSpan();
            foreach (MachineProduction mProd in RunTimeList)
                results += (DateTime)mProd.EndTime - (DateTime)mProd.StartTime;
            return results;
        }
        static SPIWareIIIDataContext context { get; set; }
        public static SPIWareIIIDataContext DataContext
        {
            get
            {
                if (context == null)
                {
                    //context = new SPIWareIIIDataContext();
                    System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                    string conn = config.AppSettings.Settings["SPIWare3ConnectionString"].Value;
                    context = new DataAccess.SPIWareIIIDataContext(conn);
                }
                return context;
            }
        }

        static List<Customer> _customers { get; set; }
        public static ObservableCollection<Customer> ocCustomers
        {
            get
            {
                if (_customers == null) _customers = DataContext.Customers.ToList();
                return _customers.OrderBy(c => c.Name).ToObservableCollection<Customer>();
            }
            set { }
        }
        static Customer _selectedCustomer { get; set; }
        public static Customer SelectedCustomer { get { return _selectedCustomer; } set { _selectedCustomer = value; } }
        public static Customer NewCustomer()
        {
            SelectedCustomer = null;
            Customer cust = new Customer();
            //c.Name = "New Customer";

            DataContext.Customers.InsertOnSubmit(cust);
            _customers.Add(cust);
            ocCustomers = _customers.OrderBy(c => c.Name).ToObservableCollection<Customer>();
            SelectedCustomer = cust;
            return cust;
        }
        public static ContactInfo NewContact()
        {
            ContactInfo ci = new ContactInfo();
            if (SelectedCustomer != null) SelectedCustomer.ContactInfos.Add(ci);
            return ci;
        }
        public static ContactInfo NewContact(ApplicationViewModel appVM)
        {
            ContactInfo ci = new ContactInfo();
            ci.ContactTypeId = 0;
            if (appVM != null && appVM.SelectedCustomer != null)
                appVM.SelectedCustomer.ContactInfos.Add(ci);
            return ci;
        }

        static List<WorkOrder> _workOrders { get; set; }
        public static ObservableCollection<WorkOrder> ocWorkOrders
        {
            get
            {
                if (_workOrders == null) _workOrders = DataContext.WorkOrders.ToList();
                return _workOrders.OrderBy(c => c.DateDue).ToObservableCollection<WorkOrder>();
            }
            set { }
        }
        public static WorkOrder SelectedWorkOrder { get; set; }
        public static WorkOrder NewWorkOrder()
        {
            WorkOrder newWO = new WorkOrder();
            newWO.CorrectedQuantity = 0;
            newWO.QuantityOrdered = 0;
            newWO.DateReceived = DateTime.Now;
            newWO.DateDue = DateTime.Now.AddDays(1);

            if (SelectedCustomer != null)
            {
                newWO.Customer = SelectedCustomer;
                SelectedCustomer.WorkOrders.Add(newWO);
            }
            else DataContext.WorkOrders.InsertOnSubmit(newWO);

            if (SelectedMaterial != null) newWO.Part = SelectedMaterial;

            _workOrders.Add(newWO);
            ocWorkOrders = _workOrders.OrderBy(c => c.DateDue).ToObservableCollection<WorkOrder>();
            SelectedWorkOrder = newWO;
            return newWO;
        }

        static List<Part> _parts { get; set; }
        public static ObservableCollection<Part> ocParts
        {
            get
            {
                if (_parts == null) _parts = DataContext.Parts.ToList();
                return _parts.OrderBy(c => c.PartNumber).ToObservableCollection<Part>();
            }
            set { }
        }
        public static Part SelectedMaterial { get; set; }
        public static Part NewPart()
        {
            if (_parts == null) _parts = DataContext.Parts.ToList();

            Part newPart = new Part();
            newPart.PartNumber = "New Part #";
            newPart.Price = 0;
            newPart.PressSize = 0;
            newPart.PressRate = 0;
            newPart.PressOpCost = 0;
            newPart.BoxPrice = 0;
            newPart.PartsPerBox = 0;
            newPart.PartsPerPallet = 0;
            newPart.PricePerBox = 0;
            newPart.DyeMixRatio = 0;
            newPart.DyeCostPerLB = 0;
            newPart.DyeCostPerPart = 0;
            newPart.MoldSetupTime = 0;
            newPart.MoldSetupCost = 0;
            newPart.StartupScrapPrice = 0;
            newPart.PartWeight = 0;
            newPart.PartsPerShot = 0;
            newPart.NaturalResin = 0;
            newPart.ResinDyePricePerPart = 0;
            newPart.AverageCycleTime_AS = 0;
            newPart.PartsPerHour_AS = 0;
            newPart.AQ41Price = 0;
            newPart.MaterialCost = 0;
            newPart.TTLPackagingPiecePerPart = 0;
            newPart.TTLCostPrePartMaterialPackaging = 0;
            newPart.LaborSecondPerPart = 0;
            newPart.LaborTTLPerPart = 0;
            newPart.OverheadFactor = 0;
            newPart.CostStartPress = 0;
            newPart.TTLPrePartMaterialPackagingLabor = 0;
            newPart.TTLCostPartAverage = 0;

            DataContext.Parts.InsertOnSubmit(newPart);
            _parts.Add(newPart);
            ocParts = _parts.OrderBy(c => c.PartNumber).ToObservableCollection<Part>();

            SelectedMaterial = newPart;
            return newPart;
        }
        static List<CustomerPart> _customerParts { get; set; }
        public static ObservableCollection<CustomerPart> CustomerParts
        {
            get
            {
                if (_customerParts == null) _customerParts = DataContext.CustomerParts.ToList();
                return _customerParts.OrderBy(c => c.Part.Description).ToObservableCollection<CustomerPart>();
            }
            set { }
        }

        static List<MachinePress> _machinePresses { get; set; }
        public static ObservableCollection<MachinePress> ocMachinePresses
        {
            get
            {
                if (_machinePresses == null) _machinePresses = DataContext.MachinePresses.ToList();
                return _machinePresses.OrderBy(c => c.PressSize).ToObservableCollection<MachinePress>();
            }
            set { }
        }
        public static MachinePress SelectedMachinePress { get; set; }
        public static MachinePress NewMachinePress()
        {
            MachinePress press = new MachinePress();
            DataContext.MachinePresses.InsertOnSubmit(press);
            _machinePresses.Add(press);
            ocMachinePresses = _machinePresses.OrderBy(c => c.PressSize).ToObservableCollection<MachinePress>();
            SelectedMachinePress = press;
            return press;
        }

        static List<MachineProduction> _machineProduction { get; set; }
        public static ObservableCollection<MachineProduction> ocProduction
        {
            get
            {
                if (_machineProduction == null) _machineProduction = DataContext.MachineProductions.ToList();
                return _machineProduction.OrderBy(m => ((DateTime)m.EndTime).Date).ToObservableCollection<MachineProduction>();
            }
            set { }
        }
        public static MachineProduction NewMachineProduction()
        {
            MachineProduction prod = new MachineProduction();
            int year = DateTime.Now.Year;
            int month = DateTime.Now.Month;
            int day = DateTime.Now.Day;

            prod.EndTime = new DateTime(year, month, day, 8, 0, 0);
            prod.StartTime = DateTime.Now.Date;

            DataContext.MachineProductions.InsertOnSubmit(prod);
            if (_machineProduction == null) _machineProduction = DataContext.MachineProductions.ToList();
            _machineProduction.Add(prod);
            ocProduction = _machineProduction.OrderBy(m => ((DateTime)m.EndTime).Date).ToObservableCollection<MachineProduction>();
            return prod;
        }

        static List<MaterialType> _materialTypes { get; set; }
        public static ObservableCollection<MaterialType> ocMaterialTypes
        {
            get
            {
                if (_materialTypes == null) _materialTypes = DataContext.MaterialTypes.ToList();
                return _materialTypes.OrderBy(s => s.MaterialType1).ToObservableCollection<MaterialType>();
            }
        }

        static List<ApplicationUser> _applicationUsers { get; set; }
        public static ObservableCollection<ApplicationUser> ApplicationUsers
        {
            get
            {
                if (_applicationUsers == null) _applicationUsers = DataContext.ApplicationUsers.ToList();
                return _applicationUsers.OrderBy(u => u.LastName).OrderBy(f => f.FirstName).ToObservableCollection<ApplicationUser>();
            }
        }
        public static ApplicationUser SelectedUser { get; set; }
        #region Static Functions
        public static ObservableCollection<Part> localParts()
        {
            if (SelectedCustomer != null) return localParts(SelectedCustomer);
            else throw new ArgumentNullException("Customer must be Selected First", new Exception());
        }
        public static ObservableCollection<Part> localParts(Customer customer)
        {
            if (_parts == null) _parts = DataContext.Parts.ToList();

            return (from p in ocParts
                    join cp in CustomerParts on p.PartsId equals cp.PartsId
                    where cp.CustomerId == customer.CustomerId
                    select p).OrderBy(c => c.Description).ToObservableCollection<Part>();
        }

        public static void ClearSelected(List<Type> tt)
        {
            foreach (Type t in tt)
            {
                switch (t.Name)
                {
                    case "Customer": SelectedCustomer = null; break;
                    case "Part": SelectedMaterial = null; break;
                    case "MachinePress": SelectedMachinePress = null; break;
                    case "WorkOrder": SelectedWorkOrder = null; break;
                    case "ApplicationUser": SelectedUser = null; break;
                    case "MaterialType": SelectedMaterial = null; break;
                }
            }
        }

        public static List<Type> AllSelectable
        {
            get
            {
                List<Type> results = new List<Type> { typeof(Customer), typeof(WorkOrder), typeof(Part), typeof(MachinePress), typeof(ApplicationUser), typeof(MaterialType) };
                return results;
            }
        }
        public static void ClearAllExcept(List<Type> tt)
        {
            List<Type> list = AllSelectable;
            foreach (Type t in tt)
                if (list.Contains(t)) list.Remove(t);
            ClearSelected(list);
        }


        public static ObservableCollection<MachineProduction> GetFilteredProduction(DateTime endDate)
        {
            DateTime begDate = endDate.Date.AddDays(-1);
            return ApplicationData.ocProduction
                .Where(d => (DateTime)d.StartTime >= begDate && (DateTime)d.EndTime <= endDate)
                .OrderBy(p => p.MachinePress.MachineNumber)
                .ToObservableCollection<MachineProduction>();
        }
        #endregion
    }
}
